package com.userqiao.linework.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.face.MatchRequest;
import com.userqiao.linework.dao.*;
import com.userqiao.linework.entity.SystemConstants;
import com.userqiao.linework.entity.TbCheckin;
import com.userqiao.linework.entity.TbFaceModel;
import com.userqiao.linework.entity.vo.CheckinVo;
import com.userqiao.linework.exception.LineWorkException;
import com.userqiao.linework.service.CheckinService;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.MalformedURLException;

import java.util.*;

/**
 * @author：userqiao
 * @email：userqiao@163.com
 * @date：2021/2/22 12:50
 */
@Service
@Slf4j
public class CheckinServiceImpl implements CheckinService {

    @Autowired
    private SystemConstants systemConstants;
    @Autowired
    private TbHolidaysDao holidaysDao;
    @Autowired
    private TbWorkdayDao workdayDao;
    @Autowired
    private TbCheckinDao checkinDao;
    @Autowired
    private TbFaceModelDao faceModelDao;
    @Autowired
    private TbCityDao tbCityDao;
    @Autowired
    private AipFace aipFace;

    @Override
    public String validCanCheckIn(int userId, String date) {
        boolean bool_1 = holidaysDao.searchTodayIsHolidays() != null ? true : false;
        boolean bool_2 = workdayDao.searchTodayIsWorkday() != null ? true : false;
        String type = "工作日";
        if (DateUtil.date().isWeekend()) {
            type = "节假日";
        }
        if (bool_1) {
            type = "节假日";
        } else if (bool_2) {
            type = "工作日";
        }
        if (type.equals("节假日")) {
            return "节假日不需要考勤";
        }
        DateTime now = DateUtil.date();
        String start = DateUtil.today() + " " + systemConstants.attendanceStartTime;
        String end = DateUtil.today() + " " + systemConstants.attendanceEndTime;
        DateTime attendanceStart = DateUtil.parse(start);
        DateTime attendanceEnd = DateUtil.parse(end);
        if (now.isBefore(attendanceStart)) {
            return "没有到上班考勤开始时间";
        } else if (now.isAfter(attendanceEnd)) {
            return "超过了上班考勤结束时间";
        } else {
            Map map = new HashMap();
            map.put("userId", userId);
            map.put("date", date);
            map.put("start", start);
            map.put("end", end);
            boolean bool = checkinDao.haveCheckin(map) != null ? true : false;
            return bool ? "今日已经考勤，不用重复考勤" : "可以考勤";
        }
    }

    @Override
    public void checkin(CheckinVo form, int userId, String path) {
        //判断签到
        //当前时间
        Date d1 = DateUtil.date();
        //上班时间
        Date d2 = DateUtil.parse(DateUtil.today() + " " + systemConstants.attendanceTime);
        //签到结束时间
        Date d3 = DateUtil.parse(DateUtil.today() + " " + systemConstants.attendanceEndTime);
        int status = 1;
        if (d1.compareTo(d2) <= 0) {
            // 正常签到
            status = 1;
        } else if (d1.compareTo(d2) > 0 && d1.compareTo(d3) < 0) {
            //迟到
            status = 2;
        } else {
            // 旷工一天
            status = 3;
        }
        //查询签到人的人脸模型数据
        String faceModel = faceModelDao.searchFaceModel(userId);
        if (faceModel == null) {
            throw new LineWorkException("不存在人脸模型");
        }
        List<MatchRequest> requests = new ArrayList<>();
        requests.add(new MatchRequest(faceModel, "FACE_TOKEN"));
        String image = Base64.encode(FileUtil.file(path));
        requests.add(new MatchRequest(image, "BASE64"));
        JSONObject resultJSON = aipFace.match(requests);
        Map<String, Object> resultMap = resultJSON.toMap();
        HashMap<String, Object> resultData = (HashMap<String, Object>) resultMap.get("result");
        // 获取相似度分数
        Double score = (Double) resultData.get("score");
        if (score < 90) {
            throw new LineWorkException("签到无效，非本人签到");
        } else if (score > 90) {
            int risk = 1;
            if (form.getCity() != null && form.getCity().length() > 0 && form.getDistrict() != null && form.getDistrict().length() > 0) {
                String code = tbCityDao.searchCode(form.getCity());
                try {
                    String url = "http://m." + code + ".bendibao.com/news/yqdengji/?qu=" + form.getDistrict();
                    Document document = Jsoup.connect(url).get();
                    Elements elements = document.getElementsByClass(" list-detail");
                    for (Element one : elements) {
                        String result = one.text().split(" ")[1];
                        if ("高风险".equals(result)) {
                            risk = 3;
                            //发送告警邮件
                        } else if ("中风险".equals(result)) {
                            risk = risk < 2 ? 2 : risk;
                        }
                    }
                } catch (IOException e) {
                    log.error("执行异常", e);
                    throw new LineWorkException("获取风险等级失败");
                }
                //保存签到记录
                TbCheckin entity = new TbCheckin();
                entity.setUserId(userId);
                entity.setAddress(form.getAddress());
                entity.setCountry(form.getCountry());
                entity.setProvince(form.getProvince());
                entity.setCity(form.getCity());
                entity.setDistrict(form.getDistrict());
                entity.setStatus((byte) status);
                entity.setRisk(risk);
                entity.setDate(DateUtil.today());
                entity.setCreateTime(d1);
                checkinDao.insert(entity);
            }

        }
    }

    @Override
    public void createFaceModel(int userId, String path) {
        // 将图片转为Base64编码
        String image = Base64.encode(FileUtil.file(path));
        String imageType = "BASE64";
        String groupId = "test";
        JSONObject result = aipFace.addUser(image, imageType, groupId, Integer.toString(userId), new HashMap<>());
        Map<String, Object> resultMap = result.toMap();
        HashMap<String, String> resultData = (HashMap<String, String>) resultMap.get("result");
        TbFaceModel entity = new TbFaceModel();
        entity.setUserId(userId);
        entity.setFaceModel(resultData.get("face_token"));
        faceModelDao.insert(entity);
    }

    @Override
    public Map searchTodayCheckin(int userId) {
        return checkinDao.searchTodayCheckin(userId);
    }

    @Override
    public long searchCheckinDays(int userId) {
        return checkinDao.searchCheckinDays(userId);
    }

    @Override
    public List<Map> searchWeekCheckin(Map param) {
        // 查询可以打卡的日期、非工作日、节假日
        List<Map> checkinList = checkinDao.searchWeekCheckin(param);
        List<Map> holidaysList = holidaysDao.getHolidayInRange(param);
        List<Map> workdaysList = workdayDao.getWorkDayInRange(param);
        // 读取开始时间和结束时间
        DateTime startDate = DateUtil.parseDate(param.get("startDate").toString());
        DateTime endDate = DateUtil.parseDate(param.get("endDate").toString());
        DateRange range = DateUtil.range(startDate, endDate, DateField.DAY_OF_MONTH);
        List list = new ArrayList();
        range.forEach(one -> {
            String date = one.toString("yyyy-MM-dd");
            //查看今天是不是假期或者工作日
            String type = "工作日";
            if (one.isWeekend()) {
                type = "节假日";
            }
            if (holidaysList != null && holidaysList.contains(date)) {
                type = "节假日";
            } else if (workdaysList != null && workdaysList.contains(date)) {
                type = "工作日";
            }

            String status = "";
            if (type.equals("工作日") && DateUtil.compare(one, DateUtil.date()) <= 0) {
                status = "缺勤";
                boolean flag = false;
                for (Map<String, String> map : checkinList) {
                    if (map.containsValue(date)) {
                        status = map.get("status");
                        flag = true;
                        break;
                    }
                    DateTime endTime = DateUtil.parse(DateUtil.today() + " " + systemConstants.attendanceEndTime);
                    String today = DateUtil.today();
                    if (date.equals(today) && DateUtil.date().isBefore(endTime) && flag == false) {
                        status = "";
                    }
                }
            }
            Map map = new HashMap();
            map.put("date", date);
            map.put("status", status);
            map.put("type", type);
            map.put("day", one.dayOfWeekEnum().toChinese("周"));
            list.add(map);
        });
        return list;
    }

    @Override
    public List<Map> searchMonthCheckin(Map param) {
        return this.searchWeekCheckin(param);
    }
}
